///////////////////////////////////////////////////////////////////////////////
// File:        main.c
// Author:      671643387@qq.com
// Description:
///////////////////////////////////////////////////////////////////////////////

#include <signal.h>
#include <stdio.h>
#if defined(__WINDOWS__)
#include <WinSock2.h>
#include <crtdbg.h>
#endif
#include "pio/server.h"

///////////////////////////////////////////////////////////////////////////////

#define HOST    "0.0.0.0"
#define PORT    8888
#define BACKLOG 1024

static struct pio_server* gserv = NULL;

///////////////////////////////////////////////////////////////////////////////

static void dump_statics(struct pio_server* serv)
{
    int x = 0;
    struct pio_worker_statics worksta;
    struct pio_server_statics servsta;
    pio_server_get_statics(serv, &servsta);
    
    printf("-------------------------------------------------\n");
    printf("address:       %s\n", servsta.address);
    printf("port:          %d\n", servsta.port);
    printf("backlog:       %d\n", servsta.backlog);
    printf("id_gen:        %d\n", servsta.id_gen);
    printf("conn_total:    %d\n", servsta.conn_total);
    printf("conn_load:     %d\n", servsta.conn_load);
    printf("worker:        %d\n", servsta.worker);

    for (; x < servsta.worker; ++x)
    {
        printf("\n");
        pio_worker_get_statics(pio_server_get_worker(serv, x), &worksta);
        printf("id:            %ld\n", worksta.id);
        printf("conn_load:     %d\n", worksta.conn_load);
    }

    printf("-------------------------------------------------\n");
}

static void signal_int(int signal)
{
    if (signal == SIGINT)
    {
        dump_statics(gserv);
        pio_server_stop(gserv);
    }
}

///////////////////////////////////////////////////////////////////////////////

static void on_connection_establised(struct pio_connection* conn)
{
    //printf("new connection: %d\n", pio_connection_get_id(conn));
}

static void on_connection_read(struct pio_connection* conn)
{
    char buff[0x1000];
    int ret = pio_connection_read(conn, buff, sizeof(buff), 0);
    if (ret != SOCKET_ERROR)
    {
        if (ret != SOCKET_ERROR_WOULDBLOCK)
        {
            pio_connection_notify_write(conn);
            pio_connection_write(conn, buff, ret, 0);
        }

        return;
    }

    pio_connection_close(conn);
}

static void on_connection_write(struct pio_connection* conn)
{
    //printf("connection %d flushed message\n", 
        //pio_connection_get_id(conn));
}

static void on_connection_close(struct pio_connection* conn)
{
    //printf("connection %d closing\n", 
    //    pio_connection_get_id(conn));
}

///////////////////////////////////////////////////////////////////////////////

int main(int argc, char* argv[])
{
    struct pio_server* serv = NULL;

#if defined(__WINDOWS__)
    WSADATA wsaData;
    WSAStartup(MAKEWORD(2,2), &wsaData);
    //_CrtSetBreakAlloc(107);
#endif

    serv = pio_server_new();
    if (serv)
    {
        signal(SIGINT, signal_int);
        gserv = serv;

        pio_server_config_worker(serv, 1);
        pio_server_set_connection_establised_fn(serv, on_connection_establised);
        pio_server_set_connection_read_fn(serv, on_connection_read);
        pio_server_set_connection_write_fn(serv, on_connection_write);
        pio_server_set_connection_close_fn(serv, on_connection_close);

        if (0 == pio_server_open(serv, HOST, PORT, BACKLOG))
        {
            printf("server is listen on %s:%d\n", HOST, PORT);
            pio_server_run(serv);
        }
        pio_server_free(serv);
    }

#if defined(__WINDOWS__)
    WSACleanup();
    _CrtDumpMemoryLeaks();
#endif

    return 0;
}
